// ==UserScript==
// @name        GOAuth2
// @description Google OAuth2 API for userscripts
// @version     2.0.0
// @author      Lari Rasku <lari.o.rasku@gmail.com>
// @license     MIT
// ==Requires==
// @match       https://www.googleapis.com/oauth2/v2/*
// @grant       GM_xmlhttpRequest
// ==/UserScript==

// Copyright (c) 2014-5 Lari Rasku <lari.o.rasku@gmail.com>
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

GOAuth2 = {};

GOAuth2.authorize = function (params, callback) {
  GM_xmlhttpRequest({
    method: 'GET',
    url: GOAuth2.getAuthUrl(params),
    onerror: callback,
    onload: function (response) {
      response = GOAuth2.urldecode(response.finalUrl.split('#')[1] || '');
      if (!('access_token' in response)) {
        callback('no access token in fragment');
      } else {
        GOAuth2.validate(params, response, callback);
      }
    },
  });
}

GOAuth2.validate = function (credentials, tokenObj, callback) {
  GM_xmlhttpRequest({
    method: 'GET',
    url: 'https://www.googleapis.com/oauth2/v1/tokeninfo?' +
         GOAuth2.urlencode(tokenObj),
    onerror: callback,
    onload: function (response) {
      try {
        response = JSON.parse(response.responseText);
      } catch (e) {
        return callback(e);
      }
      if (response.scope === credentials.scope
      && response.audience.split('.')[0] == credentials.client_id) {
        callback(null, tokenObj);
      } else {
        callback(response);
      }
    },
  });
}

GOAuth2.getAuthUrl = function (params) {
  params.response_type = 'token';
  return 'https://accounts.google.com/o/oauth2/auth?' +
         GOAuth2.urlencode(params);
}

GOAuth2.urlencode = function (obj) {
  var pairs = [];
  for (var key in obj) {
    pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
  }
  return pairs.join('&');
}

GOAuth2.urldecode = function (str) {
  var obj = {};
  var pairs = str.split('&');
  for (var i = 0, pair; pair = pairs[i]; ++i) {
    pair = pair.split('=');
    obj[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  }
  return obj;
}
